﻿#include "souistd.h"
#include "control/SSpinButtonCtrl.h"

namespace SOUI {
    SSpinButtonCtrl::SSpinButtonCtrl(void)
        : m_pDownSkin(nullptr)
        , m_pUpSkin(nullptr)
        , m_iActionBtn(ACTION_NULL)
        , m_nMin(0)
        , m_nMax(100)
        , m_nValue(0)
        , m_uStep(1)
        , m_bCircle(TRUE) {
        GetEventSet()->addEvent(EVENTID(EventSpinValue2String));
    }
    
    SSpinButtonCtrl::~SSpinButtonCtrl(void) {
    }
    
    
    CSize SSpinButtonCtrl::GetDesiredSize(int wid, int hei) {
        CSize szRet;
        if(GetLayoutParam()->IsSpecifiedSize(Horz)) {
            szRet.cx = GetLayoutParam()->GetSpecifiedSize(Horz).toPixelSize(GetScale());
        } else {
            szRet.cx = m_pDownSkin->GetSkinSize().cx;
        }
        if(GetLayoutParam()->IsSpecifiedSize(Vert)) {
            szRet.cy = GetLayoutParam()->GetSpecifiedSize(Vert).toPixelSize(GetScale());
        } else {
            szRet.cy = m_pDownSkin->GetSkinSize().cy  + m_pUpSkin->GetSkinSize().cy;
        }
        
        return szRet;
    }
    
    
    HRESULT SSpinButtonCtrl::OnAttrValue(const SStringW &strValue, BOOL bLoading) {
        m_nValue = _wtoi(strValue);
        if(!bLoading) {
            OnValueChanged();
        }
        return S_OK;
    }
    
    void SSpinButtonCtrl::OnValueChanged(bool bInit) {
        if (bInit) {
            EventSpinValue2String evt(this);
            evt.bInit = bInit;
            evt.nValue = m_nValue;
            FireEvent(evt);
        }
    }
    
    
    void SSpinButtonCtrl::OnLButtonDown(UINT nFlags, CPoint point) {
        SWindow::OnLButtonDown(nFlags, point);
        SetFocus();
        OnClick();
        Invalidate();
        SetTimer(1, 200);
    }
    
    void SSpinButtonCtrl::OnLButtonUp(UINT nFlags, CPoint point) {
        SWindow::OnLButtonUp(nFlags, point);
        KillTimer(1);
        Invalidate();
    }
    
    void SSpinButtonCtrl::OnMouseMove(UINT nFlags, CPoint point) {
        CRect rcClient = GetClientRect();
        if(rcClient.PtInRect(point)) {
            if (point.y > (rcClient.top + rcClient.Height() / 2)) {
                m_iActionBtn = ACTION_DOWN;
            } else {
                m_iActionBtn = ACTION_UP;
            }
        } else {
            m_iActionBtn = ACTION_NULL;
        }
    }
    
    
    void SSpinButtonCtrl::OnColorize(COLORREF cr) {
        __super::OnColorize(cr);
        
        if ( m_pUpSkin ) {
            m_pUpSkin->OnColorize(cr);
        }
        if ( m_pDownSkin ) {
            m_pDownSkin->OnColorize(cr);
        }
    }
    
    
    void SSpinButtonCtrl::OnPaint(IRenderTarget *pRT) {
        SWindow::OnPaint(pRT);
        CRect rcClient = GetClientRect();
        CRect rcUp = rcClient, rcDown = rcClient;
        rcUp.bottom = rcDown.top = rcClient.top + rcClient.Height() / 2;
        int iState = SState2Index::GetDefIndex(GetState(), true);
        if (m_iActionBtn == ACTION_UP) {
            m_pUpSkin->DrawByIndex(pRT, rcUp, iState);
            m_pDownSkin->DrawByIndex(pRT, rcDown, iState != 2 ? iState : 1);
        } else if(m_iActionBtn == ACTION_DOWN) {
            m_pUpSkin->DrawByIndex(pRT, rcUp, iState != 2 ? iState : 1);
            m_pDownSkin->DrawByIndex(pRT, rcDown, iState);
        } else {
            iState = iState != 2 ? iState : 0;
            m_pUpSkin->DrawByIndex(pRT, rcUp, iState);
            m_pDownSkin->DrawByIndex(pRT, rcDown, iState);
        }
    }
    void SSpinButtonCtrl::OnTimer(char cTimerId) {
        if(m_iActionBtn == ACTION_NULL) {
            return;
        }
        
        OnClick();
    }
    
    
    
    int SSpinButtonCtrl::OnCreate(void *) {
        int nRet = __super::OnCreate(NULL);
        if (nRet != 0) {
            return nRet;
        }
        return 0;
    }
    
    void SSpinButtonCtrl::OnClick() {
        SASSERT(m_iActionBtn != ACTION_NULL);
        
        if (m_iActionBtn == ACTION_DOWN) {
            m_nValue = -m_uStep;
        } else {
            m_nValue = m_uStep;
        }
        OnValueChanged(true);
    }
    
    void SSpinButtonCtrl::OnSkinChanged() {
        __super::OnSkinChanged();
        updateSkin(m_pUpSkin);
        updateSkin(m_pDownSkin);
    }
    
    void SSpinButtonCtrl::SetStep(double fStep) {
        m_uStep = fStep;
    }
    
}